import logging
import time

import pymysql
from selenium import webdriver
from selenium.common import *
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

from config.config import *


class KeyWord():
    def __init__(self, driver):
        self.env = config["dev"]  # 系统环境变量
        self.db_config = self.env["db_config"]  # 数据库环境变量

        # 调试
        # self.driver = webdriver.Chrome()
        self.driver = driver
        self.wait = WebDriverWait(self.driver, 10)

    # 打开网页
    def open_url(self, url):
        try:
            self.driver.get(url)
        except Exception as e:
            logging.error(f"打开网页{url}失败：{e}")
            raise

    # 元素显示等待-visibility
    def element_until_visibility(self, by, value):
        """
            visibility_of_element_located：检查元素在DOM中既要存在，也要是可见（display！=None，visibility=visible）
            presence_of_element_located：检查元素在DOM中既要存在，不需要是否可见（display！=None，visibility=visible）
        """
        locator = (by, value)
        try:
            self.wait.until(EC.visibility_of_element_located(locator))
            el = self.driver.find_element(*locator)
            return el
        except TimeoutException as e:
            logging.error(f"该元素底层可能未封装属于不可见元素，请切换presence不可见等待:{e}")
            raise

    # 多元素显示等待-visibility
    def elements_until_visibility(self, by, value):
        locator = (by, value)
        try:
            self.wait.until(EC.visibility_of_element_located(locator))
            el = self.driver.find_elements(*locator)
            return el
        except TimeoutException as e:
            logging.error(f"该元素底层可能未封装属于不可见元素，请切换presence不可见等待:{e}")
            raise

    # 元素显示等待-presence
    def element_until_presence(self, by, value):
        """
            visibility_of_element_located：检查元素在DOM中既要存在，也要是 可见（display！=None，visibility=visible）
            presence_of_element_located：检查元素在DOM中既要存在，不需要是否 可见（display！=None，visibility=visible）
        """
        self.wait.until(EC.presence_of_element_located((by, value)))
        el = self.driver.find_element(by, value)
        return el

    # 元素等待+点击
    def click_el_until_visibility(self, by, value):
        locator = (by, value)
        try:
            self.element_until_visibility(*locator).click()
        except NoSuchElementException as e:
            logging.error(f"按钮-{locator}元素未找到:{e}")
            raise
        except TimeoutException as e:
            logging.error(f"元素{locator}等待超时,请检查{locator}：{e}")
            raise

    # 元素等待+点击
    def click_el_until_presence(self, by, value):
        locator = (by, value)
        try:
            self.element_until_presence(*locator).click()
        except NoSuchElementException as e:
            logging.error(f"按钮-{locator}元素未找到:{e}")
            raise
        except TimeoutException as e:
            logging.error(f"该元素底层可能未封装属于不可见元素，请切换visibility不可见等待:{e}")
            raise

    # 文本显示等待
    def text_until_visibility(self, by, value):
        locator = (by, value)
        try:
            time.sleep(3)
            el = self.element_until_visibility(*locator).text
            return el
        except TimeoutException as e:
            logging.error(f"文本定位{locator}获取超时:{e}")
            raise

    # 文本显示等待
    def text_until_presence(self, by, value):
        try:
            el = self.element_until_presence(by, value).text
            return el
        except TimeoutException as e:
            logging.error(f"该文本元素底层可能未封装属于不可见元素，请切换visibility不可见等待:{e}")
            raise

    # 输入信息
    def send_content(self, by, value, content):
        locator = (by, value)
        try:
            self.element_until_presence(*locator).clear()
            self.element_until_presence(*locator).send_keys(content)
        except NoSuchElementException as e:
            logging.error(f"输入框-{locator}元素未找到:{e}")
            raise

    # 输入信息+enter回车
    def send_keys_enter(self, by, value, content):
        locator = (by, value)
        try:
            self.element_until_presence(*locator).send_keys(content)
            self.element_until_presence(*locator).send_keys(Keys.ENTER)
        except NoSuchElementException as e:
            logging.error(f"输入框-{locator}元素未找到:{e}")
            raise

    # 切换页签窗体
    def change_window(self, n):
        windows = self.driver.window_handles
        try:
            self.driver.switch_to.window(windows[n])
        except TimeoutException as e:
            logging.error(f"切换window失败,请检查'{windows[n]}'是否正确：{e}")
            raise

    # 切入iframe窗体-
    """ 注意：只能上级切换下级，不能逆向"""

    def change_into_iframe(self, by, value):
        locator = (by, value)
        el = self.element_until_presence(*locator)
        try:
            time.sleep(2)
            self.driver.switch_to.frame(el)
            # time.sleep(2)
        except TimeoutException as e:
            logging.error(f"切换frame失败,请检查{locator}是否正确：{e}")
            raise
            # 切进当前窗体

    # 切换上层-父frame
    def change_parent_frame(self):
        try:
            time.sleep(2)
            self.driver.switch_to.parent_frame()
            time.sleep(2)
        except:
            logging.error(f"切换到上层iframe框架失败,请检查是否切换正确")
            raise

    # 切回最上层frame
    def change_top_frame(self):
        try:
            self.driver.switch_to.default_content()
        except:
            logging.error(f"切换到顶层框架失败,请检查是否切换正确")
            raise

    # 点击alert弹框确认
    def click_alert_btn(self):
        try:
            alert = self.driver.switch_to.alert
            alert.accept()
        except:
            logging.error(f"点击弹框确认按钮失败")
            raise

    # 获取alert弹框文本
    def get_alert_text(self):
        try:
            alert = self.driver.switch_to.alert
            return alert.text

        except:
            logging.error(f"获取弹框文本失败")
            raise

    # 按住并拖动指定xy偏移量
    def drag_and_drop(self, by, value, xoffset, yoffset):
        locator = (by, value)
        try:
            ActionChains(self.driver).drag_and_drop_by_offset(self.element_until_presence(*locator), xoffset,
                                                              yoffset).perform()
        except NoSuchElementException as e:
            logging.error(f"定位{locator}元素未找到:{e}")
            raise
        except TimeoutException as e:
            logging.error(f"坐标{[xoffset, yoffset]}获取超时:{e}")
            raise

    # 滚动页面到指定元素出现
    def scroll_by_amount(self, x, y):
        self.driver.execute_script(f"window.scrollTo({x},{y})")
        # ActionChains(self.driver).scroll_by_amount(delta_x, delta_y).perform()

    # select下拉框
    def select_box(self, by, value, option_value):
        locator = (by, value)
        select = Select(self.element_until_presence(*locator))
        select.select_by_value(option_value)

    # 数据库校验
    def sql_check(self, sql):
        try:
            conn = pymysql.Connect(**self.db_config)
            cursor = conn.cursor()
            cursor.execute(query=sql)
            conn.commit()  # 提交更改
            if 'select' in sql:
                sql_data = cursor.fetchone()
                return sql_data[0]
            elif 'delete' in sql:
                pass
            conn.close()
        except:
            logging.error(f"数据库连接失败,请重新检查数据库配置")
            raise

    # 断言
    def assert_case(self, actual_result, sign, expect_result):
        assert str(actual_result) + f"{sign}" + str(expect_result)
